package me.flyray.bsin.server.impl;

import com.alibaba.fastjson.JSONObject;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;

import com.github.binarywang.wxpay.bean.applyment.WxPayApplyment4SubCreateRequest;
import com.github.binarywang.wxpay.bean.applyment.WxPayApplymentCreateResult;
import com.github.binarywang.wxpay.bean.media.ImageUploadResult;
import com.github.binarywang.wxpay.service.Applyment4SubService;
import com.github.binarywang.wxpay.service.impl.Applyment4SubServiceImpl;

import lombok.extern.slf4j.Slf4j;
import me.flyray.bsin.domain.entity.Merchant;
import me.flyray.bsin.domain.entity.PayChannelConfig;
import me.flyray.bsin.facade.service.MerchantService;
import me.flyray.bsin.infrastructure.biz.paychannel.PayChannelConfigBiz;
import me.flyray.bsin.oss.OssUtil;
import me.flyray.bsin.payment.channel.wxpay.WxServiceUtil;
import me.flyray.bsin.payment.enums.PayChannelInterfaceEnum;
import me.flyray.bsin.exception.BusinessException;
import me.flyray.bsin.facade.service.PayMerchantEntryService;
import me.flyray.bsin.payment.channel.wxpay.BsinWxPayServiceUtil;
import me.flyray.bsin.security.contex.LoginInfoContextHelper;
import me.flyray.bsin.security.domain.LoginUser;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.shenyu.client.apache.dubbo.annotation.ShenyuDubboService;
import org.apache.shenyu.client.apidocs.annotations.ApiDoc;
import org.apache.shenyu.client.apidocs.annotations.ApiModule;
import org.apache.shenyu.client.dubbo.common.annotation.ShenyuDubboClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.InputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

import com.github.binarywang.wxpay.bean.applyment.ApplymentStateQueryResult;

/**
 * 支付商户进件
 */

@Slf4j
@ShenyuDubboService(path = "/payMerchantEntry", timeout = 6000)
@ApiModule(value = "payMerchantEntry")
@Service
public class PayMerchantEntryServiceImpl implements PayMerchantEntryService {

    @Autowired
    private BsinWxPayServiceUtil bsinWxPayServiceUtil;
    @Autowired
    private PayChannelConfigBiz payChannelConfigBiz;

    @DubboReference(version = "${dubbo.provider.version}")
    private MerchantService merchantService;

    @Override
    @ShenyuDubboClient("/apply")
    @ApiDoc(desc = "apply")
    public Map<String, Object> apply(Map<String, Object> requestMap) {
        log.info("开始处理支付渠道进件，请求参数：{}", requestMap);
        
        String payChannel = MapUtils.getString(requestMap, "payChannel");
        if (StringUtils.isEmpty(payChannel)) {
            throw new BusinessException("PAY_CHANNEL_EMPTY", "支付渠道参数不能为空");
        }
        
        PayChannelInterfaceEnum channelEnum = PayChannelInterfaceEnum.getInstanceById(payChannel);
        if (channelEnum == null) {
            throw new BusinessException("UNSUPPORTED_PAY_CHANNEL", "不支持的支付渠道：" + payChannel);
        }
        
        try {
            LoginUser loginUser = LoginInfoContextHelper.getLoginUser();
            Map<String, Object> result = switch (channelEnum) {
                case WXPAY -> handleWxPayEntry(requestMap, loginUser);
                case ALIPAY -> handleAliPayEntry(requestMap, loginUser);
                default -> throw new BusinessException("UNIMPLEMENTED_PAY_CHANNEL", "未实现的支付渠道进件处理：" + channelEnum.getDesc());
            };
            
            log.info("支付渠道进件处理完成，渠道：{}", payChannel);
            return result;
            
        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("支付渠道进件处理异常，渠道：{}，错误：{}", payChannel, e.getMessage(), e);
            throw new BusinessException("PAY_ENTRY_ERROR", "支付渠道进件处理异常：" + e.getMessage());
        }
    }

    @ShenyuDubboClient("/mediaUpload")
    @ApiDoc(desc = "mediaUpload")
    @Override
    public Map<String, Object> mediaUpload(Map<String, Object> requestMap) {
        String imageUrl = MapUtils.getString(requestMap, "imageUrl");
        if (StringUtils.isEmpty(imageUrl)) {
            throw new BusinessException("IMAGE_URL_EMPTY", "图片URL参数不能为空");
        }
        
        log.info("开始微信进件素材上传，图片URL：{}", imageUrl);
        
        try {
            Merchant merchant = getMerchant(requestMap);
            WxPayService wxPayService = getWxPayService(merchant, requestMap);
            
            String fileName = getFileNameFromUrl(imageUrl);
            InputStream inputStream = OssUtil.getInputStreamByUrl(imageUrl);
            ImageUploadResult result = wxPayService.getMerchantMediaService().imageUploadV3(inputStream, fileName);
            
            log.info("图片上传成功，媒体文件标识：{}", result.getMediaId());
            return buildUploadResult(result, imageUrl);
            
        } catch (BusinessException e) {
            throw e;
        } catch (WxPayException e) {
            log.error("微信支付图片上传失败，URL：{}，错误：{}", imageUrl, e.getMessage(), e);
            throw new BusinessException("WX_PAY_UPLOAD_ERROR", "微信支付图片上传失败：" + e.getMessage());
        } catch (Exception e) {
            log.error("图片处理失败，URL：{}，错误：{}", imageUrl, e.getMessage(), e);
            throw new BusinessException("IMAGE_PROCESS_ERROR", "图片处理失败：" + e.getMessage());
        }
    }


    private Merchant getMerchant(Map<String, Object> requestMap) {
        String merchantNo = MapUtils.getString(requestMap, "merchantNo");
        Map<String, Object> requestMerchantMap = new HashMap<>();
        requestMerchantMap.put("merchantNo", merchantNo);
        return merchantService.getDetail(requestMerchantMap);
    }

    private WxPayService getWxPayService(Merchant merchant, Map<String, Object> requestMap) {
        String merchantNo = MapUtils.getString(requestMap, "merchantNo");
        String merchantPayMode = MapUtils.getString(requestMap, "merchantPayMode");
        String payWay = MapUtils.getString(requestMap, "payWay");

        AtomicBoolean isCache = new AtomicBoolean(true);
        WxServiceUtil wxServiceUtil = null;
        PayChannelConfig payChannelConfig =
                payChannelConfigBiz.queryPayChannelConfig(
                        merchant.getBizRoleAppId(),
                        merchantNo,
                        payWay,
                        merchantPayMode,
                        isCache);
        WxServiceUtil wxServiceWrapper = payChannelConfigBiz.getWxServiceWrapper(payChannelConfig);
        WxPayService wxPayService = wxServiceWrapper.getWxPayService();

        if (!isCache.get()) {
            log.info("缓存中未查询到参数配置，从数据库中查询，重新写入缓存。。。");
            payChannelConfigBiz.setPayChannelConfigMapper(payChannelConfig);
        }

        return wxPayService;
    }

    private Map<String, Object> buildUploadResult(ImageUploadResult result, String imageUrl) {
        Map<String, Object> response = new HashMap<>();
        response.put("success", true);
        response.put("message", "图片上传成功");
        response.put("mediaId", result.getMediaId());
        response.put("imageUrl", imageUrl);
        response.put("uploadTime", new Date());
        return response;
    }

    private Map<String, Object> buildEntryResult(Map<String, Object> requestMap, String applymentId, String channel) {
        Map<String, Object> result = new HashMap<>();
        result.put("success", true);
        result.put("message", "支付进件申请已提交");
        result.put("applymentId", applymentId);
        result.put("status", "PENDING");
        result.put("channel", channel);
        result.put("businessCode", MapUtils.getString(requestMap, "businessCode"));
        result.put("requestJson", JSONObject.toJSONString(requestMap));
        result.put("responseJson", JSONObject.toJSONString(Map.of("applymentId", applymentId, "status", "PENDING")));
        result.put("createTime", new Date());
        return result;
    }

    /**
     * 从URL中提取文件名
     * 
     * @param imageUrl 图片URL
     * @return 文件名，如果无法提取则返回默认文件名
     */
    private String getFileNameFromUrl(String imageUrl) {
        try {
            if (StringUtils.isEmpty(imageUrl)) {
                return "image.jpg";
            }
            
            // 尝试从URL路径中提取文件名
            int lastSlashIndex = imageUrl.lastIndexOf('/');
            if (lastSlashIndex >= 0 && lastSlashIndex < imageUrl.length() - 1) {
                String fileName = imageUrl.substring(lastSlashIndex + 1);
                // 移除查询参数
                int queryIndex = fileName.indexOf('?');
                if (queryIndex > 0) {
                    fileName = fileName.substring(0, queryIndex);
                }
                // 检查是否有文件扩展名
                if (fileName.contains(".")) {
                    return fileName;
                }
            }
            
            // 如果无法从URL提取有效文件名，返回默认文件名
            return "image.jpg";
        } catch (Exception e) {
            log.warn("从URL提取文件名失败：{}", e.getMessage());
            return "image.jpg";
        }
    }

    private Map<String, Object> handleWxPayEntry(Map<String, Object> requestMap, LoginUser loginUser) {
        log.info("开始处理微信支付进件");
        
        try {
            Merchant merchant = getMerchant(requestMap);
            WxPayService wxPayService = getWxPayService(merchant, requestMap);
            
            String applymentId = simulateWxPayApplyment(requestMap, wxPayService);
            log.info("微信支付进件申请成功，申请单号：{}", applymentId);
            
            return buildEntryResult(requestMap, applymentId, "wxpay");
            
        } catch (Exception e) {
            log.error("微信支付进件处理异常：{}", e.getMessage(), e);
            throw new BusinessException("WX_PAY_ENTRY_ERROR", "微信支付进件处理异常：" + e.getMessage());
        }
    }
    

    /**
     * 微信支付进件申请
     * 使用服务商模式进行进件
     */
    private String simulateWxPayApplyment(Map<String, Object> requestMap, WxPayService wxPayService) {

        try {

            // 获取当前用户信息
            String tenantId = LoginInfoContextHelper.getTenantId();
            String merchantNo = LoginInfoContextHelper.getLoginUser().getMerchantNo();
            String storeNo = LoginInfoContextHelper.getLoginUser().getStoreNo();

            // 生成业务申请编号
            String businessCode = generateBizBillNo(tenantId, merchantNo, storeNo);
            
            // 创建服务商进件服务
            Applyment4SubService applyment4SubService = new Applyment4SubServiceImpl(wxPayService);
            
            // 构建进件请求 - 使用JSON转换的方式
            WxPayApplyment4SubCreateRequest request = buildWxPayApplyment4SubRequest(requestMap, businessCode);
            
            // 调用微信支付进件API
            WxPayApplymentCreateResult result = applyment4SubService.createApply(request);
            
            String applymentId = result.getApplymentId();
            log.info("微信支付进件申请成功，申请单号：{}，业务编号：{}", applymentId, businessCode);
            
            return applymentId;
            
        } catch (WxPayException e) {
            log.error("微信支付进件申请失败：{}", e.getMessage(), e);
            throw new BusinessException("WX_PAY_APPLYMENT_ERROR", "微信支付进件申请失败：" + e.getMessage());
        } catch (Exception e) {
            log.error("微信支付进件申请异常：{}", e.getMessage(), e);
            throw new BusinessException("WX_PAY_APPLYMENT_ERROR", "微信支付进件申请异常：" + e.getMessage());
        }
    }
    
    /**
     * 生成业务申请编号
     */
    private String generateBizBillNo(String tenantId, String merchantNo, String storeNo) {
        String timestamp = String.valueOf(System.currentTimeMillis());
        String random = String.valueOf((int)(Math.random() * 1000));
        return String.format("BIZ_%s_%s_%s_%s_%s", tenantId, merchantNo, storeNo, timestamp, random);
    }

    /**
     * 构建微信支付服务商进件请求
     * 使用JSON转换的方式，避免依赖特定的枚举类型
     */
    private WxPayApplyment4SubCreateRequest buildWxPayApplyment4SubRequest(Map<String, Object> requestMap, String businessCode) {
        // 构建完整的请求数据
        Map<String, Object> requestData = new HashMap<>();
        requestData.put("businessCode", businessCode);
        
        // 复制所有必要的字段
        if (requestMap.containsKey("subjectInfo")) {
            requestData.put("subjectInfo", requestMap.get("subjectInfo"));
        }
        if (requestMap.containsKey("businessInfo")) {
            requestData.put("businessInfo", requestMap.get("businessInfo"));
        }
        if (requestMap.containsKey("settlementInfo")) {
            requestData.put("settlementInfo", requestMap.get("settlementInfo"));
        }
        if (requestMap.containsKey("bankAccountInfo")) {
            requestData.put("bankAccountInfo", requestMap.get("bankAccountInfo"));
        }
        if (requestMap.containsKey("contactInfo")) {
            requestData.put("contactInfo", requestMap.get("contactInfo"));
        }
        
        // 使用JSON转换创建请求对象
        String requestJson = JSONObject.toJSONString(requestData);
        log.info("微信支付进件请求JSON：{}", requestJson);
        
        // 通过JSON转换创建请求对象
        WxPayApplyment4SubCreateRequest request = JSONObject.parseObject(requestJson, WxPayApplyment4SubCreateRequest.class);
        
        log.info("微信支付服务商进件请求构建完成，业务编号：{}", businessCode);
        return request;
    }
    
    private Map<String, Object> handleAliPayEntry(Map<String, Object> requestMap, LoginUser loginUser) {
        log.info("开始处理支付宝进件");
        
        try {
            validateAliPayEntryParams(requestMap);
            String applymentId = "ALI_" + System.currentTimeMillis();
            log.info("支付宝进件申请成功，申请单号：{}", applymentId);
            return buildEntryResult(requestMap, applymentId, "alipay");
            
        } catch (Exception e) {
            log.error("支付宝进件处理异常：{}", e.getMessage(), e);
            throw new BusinessException("ALI_PAY_ENTRY_ERROR", "支付宝进件处理异常：" + e.getMessage());
        }
    }
    
    /**
     * 验证支付宝进件参数
     */
    private void validateAliPayEntryParams(Map<String, Object> requestMap) {
        // 必填参数验证
        String businessCode = MapUtils.getString(requestMap, "businessCode");
        if (StringUtils.isEmpty(businessCode)) {
            throw new BusinessException("BUSINESS_CODE_EMPTY", "业务申请编号不能为空");
        }
        
        // 商户信息验证
        Map<String, Object> merchantInfo = (Map<String, Object>) requestMap.get("merchantInfo");
        if (merchantInfo == null) {
            throw new BusinessException("MERCHANT_INFO_EMPTY", "商户信息不能为空");
        }
    }
    
    /**
     * 进件状态查询
     */
    @Override
    @ShenyuDubboClient("/getApplyStatus")
    @ApiDoc(desc = "getApplyStatus")
    public Map<String, Object> getApplyStatus(Map<String, Object> requestMap) {
        log.info("开始查询进件状态，请求参数：{}", requestMap);
        
        String applymentId = MapUtils.getString(requestMap, "applymentId");
        if (StringUtils.isEmpty(applymentId)) {
            throw new BusinessException("APPLYMENT_ID_EMPTY", "申请单号不能为空");
        }

        String payChannel = MapUtils.getString(requestMap, "payChannel");
        if (StringUtils.isEmpty(payChannel)) {
            throw new BusinessException("PAY_CHANNEL_EMPTY", "支付渠道不能为空");
        }

        Map<String, Object> result = switch (payChannel) {
            case "WXPAY" -> {
                Merchant merchant = getMerchant(requestMap);
                yield queryWxPayStatus(applymentId, merchant, requestMap);
            }
            case "ALIPAY" -> queryAliPayStatus(applymentId);
            default -> throw new BusinessException("UNSUPPORTED_PAY_CHANNEL", "不支持的支付渠道：" + payChannel);
        };

        log.info("进件状态查询完成，申请单号：{}，状态：{}", applymentId, result.get("status"));
        return result;
    }
    
    /**
     * 查询微信支付进件状态
     */
    private Map<String, Object> queryWxPayStatus(String applymentId, Merchant merchant, Map<String, Object> requestMap) {
        log.info("开始查询微信支付进件状态，申请单号：{}", applymentId);

        WxPayService wxPayService = getWxPayService(merchant, requestMap);

        // 创建服务商进件服务
        Applyment4SubService applyment4SubService = new Applyment4SubServiceImpl(wxPayService);

        // 调用微信支付的状态查询API
        ApplymentStateQueryResult result = null;
        try {
            result = applyment4SubService.queryApplyStatusByApplymentId(applymentId);
        } catch (WxPayException e) {
            throw new RuntimeException(e);
        }

        // 构建返回结果
        Map<String, Object> response = new HashMap<>();
        response.put("success", true);
        response.put("applymentId", applymentId);
        response.put("status", result.getApplymentState().name());
        response.put("message", getStatusMessage(result.getApplymentState().name()));
        response.put("updateTime", new Date());

        // TODO 根据结果回填特约商户支付信息


        log.info("微信支付进件状态查询成功，申请单号：{}，状态：{}", applymentId, result.getApplymentState());
        return response;

    }
    
    private String getStatusMessage(String status) {
        if (status == null) return "未知状态";
        return switch (status) {
            case "SUBMITTED" -> "已提交";
            case "AUDITING" -> "审核中";
            case "APPROVED" -> "审核通过";
            case "REJECTED" -> "审核拒绝";
            case "CANCELED" -> "已取消";
            default -> "未知状态";
        };
    }
    
    /**
     * 查询支付宝进件状态
     */
    private Map<String, Object> queryAliPayStatus(String applymentId) {
        log.info("查询支付宝进件状态，申请单号：{}", applymentId);
        
        // 这里应该调用支付宝的状态查询API
        // 暂时返回模拟状态
        Map<String, Object> result = new HashMap<>();
        result.put("success", true);
        result.put("applymentId", applymentId);
        result.put("status", "PENDING"); // 可能的状态：PENDING, APPROVED, REJECTED
        result.put("message", "进件审核中");
        result.put("updateTime", new Date());
        
        return result;
    }

}
